﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MbUnit.Framework;
using HelloMVC.Interface.Repository;
using HelloMVC.Interface.Authorization;
using HelloMVC.Service;
using HelloMVC.Repository;
using HelloMVC.Controllers;
using System.Web.Mvc;
using System.Web;
using System.Web.Routing;
using System.Security.Principal;
using Moq;
using System.Web.Security;
using HelloMVC.Model;

namespace HelloMVC.Test.TestHelper
{
    static class FakeControllerFactory
    {
        public static AccountController CreateFakeAccountController()
        {
            var mockFormsAuth = new Mock<IFormsAuthenticationService>();
            var mockUser = new Mock<MembershipUser>();

            mockUser.Setup(u => u.ChangePassword(It.IsAny<string>(),
                It.Is<string>(s => s == "newPassword"))).Returns(true);

            var mockMembership = new Mock<MembershipProvider>();

            mockMembership.Setup(m => m.EnablePasswordReset).Returns(false);
            mockMembership.Setup(m => m.EnablePasswordRetrieval).Returns(false);
            mockMembership.Setup(m => m.MinRequiredNonAlphanumericCharacters).Returns(0);
            mockMembership.Setup(m => m.MinRequiredPasswordLength).Returns(6);
            mockMembership.Setup(m => m.ValidateUser(It.IsAny<string>(),
                It.Is<string>(s => s == "correct"))).Returns(true);
            mockMembership.Setup(m => m.GetUser(It.IsAny<string>(),
                It.IsAny<bool>())).Returns(mockUser.Object);
            // Registration success mock   
            MembershipCreateStatus goodStatus = MembershipCreateStatus.Success;
            mockMembership.Setup(m => m.CreateUser(It.Is<string>(s => s == "someUser"),
                It.Is<string>(s => s == "correct"),
                It.Is<String>(s => s == "email"), It.IsAny<string>(),
                It.IsAny<string>(),
                It.IsAny<bool>(),
                It.IsAny<object>(),
                out goodStatus)).Returns(mockUser.Object);
            // Registration failed mock (duplicate username)  
            MembershipCreateStatus dupeStatus = MembershipCreateStatus.DuplicateUserName;
            mockMembership.Setup(m => m.CreateUser(It.Is<string>(s => s == "someUser"),
                It.Is<string>(s => s == "badPass"),
                It.Is<string>(s => s == "DuplicateUserName"),
                It.IsAny<string>(),
                It.IsAny<string>(),
                It.IsAny<bool>(),
                It.IsAny<object>(),
                out dupeStatus));

            var mockService = new AccountMembershipService(mockMembership.Object);
            var mockResp = FakeAccountRepository();

            var mockAccountController = new AccountController(mockFormsAuth.Object, mockService, mockResp);

            return mockAccountController;
        }

        /// <summary>
        /// Fake a usally Account Repository
        /// </summary>
        /// <returns></returns>
        public static IAccountRepository FakeAccountRepository()
        {
            var mockResp = new Mock<IAccountRepository>();

            var users = new List<UserModel>
            {
                new UserModel{UserName = "Jeffrey", Email = "Jeffrey@perficient.com", Role = "Admin"},
                new UserModel{UserName = "Tom", Email = "Tom@perficient.com", Role = "Guest"}
            };

            var userDetail = new UserDetailModel
            {
                ID = "pkid",
                PhoneNumber = "123456789",
                RegisterTime = DateTime.Now
            };

            mockResp.Setup(m => m.GetAllUsers()).Returns(users);
            mockResp.Setup(m => m.GetUserDetail(It.Is<String>(id => id.Equals("pkid")))).Returns(userDetail);

            return mockResp.Object;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static HttpContextBase FakeAuthenticatedHttpContext()
        {
            var context = new Mock<HttpContextBase>();
            var request = new Mock<HttpRequestBase>();
            var response = new Mock<HttpResponseBase>();
            var session = new Mock<HttpSessionStateBase>();
            var server = new Mock<HttpServerUtilityBase>();
            var user = new Mock<IPrincipal>();
            var identity = new Mock<IIdentity>();

            context.Setup(ctx => ctx.Request).Returns(request.Object);
            context.Setup(ctx => ctx.Response).Returns(response.Object);
            context.Setup(ctx => ctx.Session).Returns(session.Object);
            context.Setup(ctx => ctx.Server).Returns(server.Object);
            context.Setup(ctx => ctx.User).Returns(user.Object);
            user.Setup(ctx => ctx.Identity).Returns(identity.Object);
            identity.Setup(id => id.IsAuthenticated).Returns(true);
            identity.Setup(id => id.Name).Returns("test");

            return context.Object;
        }

        public static void SetFakeAuthenticatedControllerContext(this AccountController controller)
        {
            var httpContext = FakeAuthenticatedHttpContext();
            ControllerContext context =
            new ControllerContext(
            new RequestContext(httpContext,
            new RouteData()), controller);
            controller.ControllerContext = context;
        }
    }
}
